#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDataStream>
#include <QTextStream>
#include <QDateTime>

QTextStream out(stdout);

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("HaiSpace聊天室");    //设置窗口标题
    this->setWindowIcon(QIcon(":/2.png"));     //设置窗口图标
    connect(this, SIGNAL(recvStartSignal()), this, SLOT(recvStartSlot()));
    connect(this, SIGNAL(classifySignal(def_msg))
            , this, SLOT(classifyMessage(def_msg)), Qt::DirectConnection);
    model = new QStringListModel(strList);    //新建QStringList模式
    ui->listOnline->setModel(model);          //设置QListView为QStringList模式
}

MainWindow::~MainWindow()
{
    delete model;
    delete ui;
}

void MainWindow::startup(int fd, int id, QString name)  //开启聊天室
{
    serv_fd = fd;       //设置与服务器进行通信的套接字
    user_id = id;       //设置当前用户的帐号
    user_name = name;   //设置当前用户的昵称
    emit recvStartSignal();     //开启接收信号
    this->show();       //显示聊天室界面
}

void MainWindow::recvStartSlot()    //开始接收来自服务器的消息
{
    pthread_t tid;
    pthread_create(&tid, NULL, recvMessage, this);  //创建新的线程
}

int MainWindow::getServerFd()
{
    return serv_fd;     //得到与服务器进行通信的套接字
}

void MainWindow::classifyFunc(def_msg msg)
{
    emit classifySignal(msg);   //发送分类处理消息信号
}

void MainWindow::classifyMessage(def_msg msg)   //分类处理消息响应
{
    if(strcmp(msg.msg_type, CHAT) == 0)     //聊天消息
    {
        QString recvMsg;
        recvMsg.sprintf("<font color='red'>%s \t\t%s</font><br> %s"
                        , msg.from_name, msg.msg_time, msg.msg_buf);    //规范格式
        ui->textMsg->append(recvMsg);           //更新消息显示区
        ui->textMsg->ensureCursorVisible();     //使消息显示区域的滚动条处于最低端
    }
    else
    {
        if(strcmp(msg.msg_type, ONLINE) == 0)   //上线消息
        {
            QString str_online;
            str_online.sprintf("%s", msg.msg_buf);  //转换格式
            onlinePeopleAdd(str_online);    //"在线人数"+1
        }
        else
        {
            if(strcmp(msg.msg_type, DOWNLINE) == 0) //下线消息
            {
                QString str_downline;
                str_downline.sprintf("%s", msg.msg_buf);    //转换格式
                downlinePeopleDesc(str_downline);   //"在线人数"-1
            }
        }
    }
}

void MainWindow::onlinePeopleAdd(QString name)
{
    strList += name;    //添加新上线用户的信息
    strList.sort();     //重新排序显示
    model->setStringList(strList);  //更新QListView
}

void MainWindow::downlinePeopleDesc(QString name)
{
    strList.removeOne(name);        //移除下线用户的信息
    model->setStringList(strList);  //更新QListView
}

void MainWindow::on_btnSend_clicked()   //"发送"按钮单击响应
{
    QString sendMsg;
    sendMsg = ui->textSend->toPlainText();  //得到发送的内容
    if(sendMsg == "")   //检测发送消息是否为空
    {
        QMessageBox::information(this, "提示", "发送消息不能为空");
        return ;
    }
    struct def_msg msg; //声明一个消息结构体对象
    strcpy(msg.msg_type, CHAT); //设置消息类型--"聊天信息"
    msg.from_id = user_id;       //设置发送人的帐号
    strcpy(msg.from_name, user_name.toStdString().c_str()); //设置发送人的昵称
    msg.to_id = 0;      //设置接收者的帐号,0表示群发消息
    strcpy(msg.msg_buf, sendMsg.toStdString().c_str()); //设置消息内容
    QDateTime time = QDateTime::currentDateTime();  //获取当前时间
    QString str_time = time.toString("yyyy-MM-dd hh:mm:ss");  //格式转换
    strcpy(msg.msg_time, str_time.toStdString().c_str());   //设置消息发送时间
    send(serv_fd, (char *)&msg, sizeof(msg), 0);    //向服务器发送消息
    ui->textSend->clear();      //清空发送区
    ui->textSend->setFocus();   //使光标保持在发送区域
}

void MainWindow::on_btnCancel_clicked()
{
    ui->textSend->clear();  //单击"取消"按钮后清空当前发送区域
}

void MainWindow::on_listOnline_doubleClicked(QModelIndex index) //QListView双击响应
{
    QString name;
    name = strList.at(index.row());     //得到双击那一栏用户的信息,为后期私聊作准备
    out<<"the name is :"<<name<<endl;
}

void MainWindow::closeEvent(QCloseEvent *e)     //重写窗口关闭事件
{
    if(QMessageBox::information(this, "提示", "确定退出聊天室?"
                                , QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
    {
        e->accept();    //关闭
    }
    else
    {
        e->ignore();    //忽略
    }
}
